<template>
  <a-config-provider :locale="locale">
    <div class="base-layout">
      <Header :siteConfig="siteConfig" />
      <section>
        <Nuxt></Nuxt>
      </section>
      <LoginModal v-if="loginModalVisible" />
      <a-modal
        width="auto"
        centered
        :footer="null"
        :closable="false"
        :visible="Boolean(previewImgSrc)"
        :body-style="{ background: 'transparent', padding: 0 }"
        wrap-class-name="preview-image-modal"
        destroy-on-close
        :mask-closable="true"
        @cancel="$store.commit('UPDATE_PREVIEW_IMGSRC', null)"
      >
        <img
          class="eg-show-image"
          :style="imageAttrStyle"
          :src="previewImgSrc"
          @click.stop
        />
      </a-modal>
      <div class="fixed-operate-block">
        <a-back-top>
          <div class="ant-back-top-inner">
            <span class="iconfont ri-plane-line"></span>
          </div>
        </a-back-top>
        <nuxt-link class="feedback-submit-block" to="/feedback" target="_blank">
          <span class="ri-message-ai-3-line iconfont"></span>
        </nuxt-link>
      </div>
      <Footer :siteConfig="siteConfig" />
    </div>
  </a-config-provider>
</template>

<script>
import { mapState } from 'vuex'
import config from '~/nuxt.config'
import createSocket from '~/util/socket'
import { noticeMap } from '~/config/optionMap'
import LoginModal from '~/components/LoginModal'
import Header from './components/Header.vue'
import Footer from './components/Footer.vue'
import zhCN from 'ant-design-vue/lib/locale-provider/zh_CN'
import { getURLSearchParams, loadWhithoutSearchURL } from '~/util'
import Logo3D from './components/Logo3D'
import MessageTemplate from './components/MessageTemplate'

export default {
  components: { LoginModal, Header, Footer },
  data () {
    return {
      locale: zhCN,
      noticeMap,
      socket: null,
      searchValue: '',
      imageAttrStyle: null
    }
  },
  computed: {
    ...mapState({
      loginModalVisible: state => state.loginModalVisible,
      userInfo: state => state.userInfo,
      notifyCount: state => state.notifyCount,
      previewImgSrc: state => state.previewImgSrc,
      siteConfig: state => state.siteConfig
    })
  },

  watch: {
    previewImgSrc (newVal) {
      const body = document.body
      const [cWidth, cHeight] = [body.clientWidth, body.clientHeight]
      const nImg = new Image()
      nImg.src = newVal
      nImg.onload = () => {
        const [width, height] = [nImg.width, nImg.height]
        if (width / height >= cWidth / cHeight) {
          const imageWidth = width > cWidth - 40 ? cWidth - 40 : width
          this.imageAttrStyle = {
            width: `${imageWidth}px`
          }
        } else {
          const imageHeight = height > cHeight - 40 ? cHeight - 40 : height
          this.imageAttrStyle = {
            height: `${imageHeight}px`
          }
        }
      }
    }
  },

  created () {
    if (process.client) {
      console.log(
        '%cThanks for using GimiShare! \n\n1071401902@qq.com\n\n佛祖保佑，Bug退散！',
        'color: #fff; font-size: 14px; font-weight: 300; text-shadow:#3eaf7c 1px 0 0,#3eaf7c 0 1px 0,#3eaf7c -1px 0 0,#3eaf7c 0 -1px 0;'
      )
      const { code, error_description: errorDescription, state } = getURLSearchParams(location.href)
      const params = state?.split(',') || []
      const [appType, operateType] = [params[0], params[1]]
      if (operateType === 'bind') {
        loadWhithoutSearchURL()
        return this.thirdApplicationAuthBind(code, appType)
      }
      if (code) {
        loadWhithoutSearchURL()
        return this.thirdApplicationAuthLogin(code, appType)
      } else if (errorDescription) {
        loadWhithoutSearchURL()
        return this.$message.error(errorDescription)
      }
      if (this.userInfo) {
        this.initWebsocket()
      }
      document.documentElement.scrollTop = 0
    }
  },

  methods: {
    /**
     * init websocket receive message
     */
    initWebsocket () {
      const protocol = location.protocol === 'http:' ? 'ws' : 'wss'
      const hostname = config.dev ? 'localhost:4000' : location.hostname
      const token = this.$cookies.get('ACCESS_TOKEN')
      this.socket = createSocket(`${protocol}://${hostname}/socket/message?id=${this.userInfo.id}&token=${token}`, {
        onopen: () => {},

        onmessage: (e) => {
          if (e.data.includes('authenticate')) {
            this.socket.close()
            this.$store.commit('UPDATE_IM_SOCKET', null)
          } else if (e.data.includes('messagepush')) {
            const message = JSON.parse(e.data)
            const countObject = {
              ...this.notifyCount,
              allCount: this.notifyCount.allCount + 1
            }
            const keyName = noticeMap[message.itemType].key
            countObject[keyName] = countObject[keyName] + 1
            this.$store.commit('UPDATE_NOTIFY_COUNT', countObject)
            this.vNodemessageTemplate(message)
          } else if (e.data.includes('"im":true')) {
            if (this.$route.path !== '/notification/im') {
              // 如果是撤回消息的通知，需要把未读消息减去1
              const count = e.data.includes('"sys":"1"') ? -1 : 1
              const countObject = {
                ...this.notifyCount,
                imCount: Math.max(this.notifyCount.imCount + count, 0)
              }
              this.$store.commit('UPDATE_NOTIFY_COUNT', countObject)
            }
            this.$store.commit('UPDATE_IM_MESSAGE', e.data)
          }
        },

        onclose () {},

        onerror () {}
      })
      this.$store.commit('UPDATE_IM_SOCKET', this.socket)
    },

    /**
     * gitee, github第三方授权登录
     * @param {*} code
     */
    async thirdApplicationAuthLogin (code, type) {
      try {
        const { data } = await this.$axios.post(`/gimishare/api/v1/users/auth-${type}`, { code })
        this.$message.success('登录成功')
        this.$cookies.set('ACCESS_TOKEN', data.accessToken, {
          path: '/',
          maxAge: 60 * 60 * 24 * 7
        })
        setTimeout(() => {
          location.reload()
        }, 1000)
      } catch (error) {
        console.log(error)
      }
    },

    async thirdApplicationAuthBind (code, type) {
      try {
        await this.$axios.post(`/gimishare/api/v1/users/bind-${type}`, { code })
        this.$message.success(`${type} 授权绑定成功`)
        window.opener.location.reload()
      } catch (e) {} finally {
        setTimeout(() => {
          window.close()
        }, 1000)
      }
    },

    vNodemessageTemplate (message) {
      const randomInstance = String(Math.random())
      this.$notification.open({
        key: randomInstance,
        message: (h) => {
          return h(
            'div',
            {
              style: {
                display: 'flex',
                alignItems: 'center'
              }
            },
            [
              h(Logo3D, {
                props: {
                  w: 16
                }
              }),
              h(
                'span',
                {
                  style: {
                    marginLeft: '12px',
                    fontSize: '14px',
                    fontWeight: 600
                  }
                },
                '新消息提示'
              )
            ]
          )
        },
        duration: null,
        description: (h) => {
          return h(MessageTemplate, {
            props: {
              message,
              instance: randomInstance
            }
          })
        }
      })
    }
  }
}
</script>

<style scoped lang="less">
.base-layout {
  background: #f5f5f5;
  section {
    min-height: ~"calc(100vh - 119px)";
    border: 1px solid transparent;
  }
  .fixed-operate-block {
    position: fixed;
    right: 30px;
    bottom: 20px;
    z-index: 10;
    .ant-back-top {
      position: static;
    }
    .feedback-submit-block,
    .ant-back-top-inner {
      height: 40px;
      width: 40px;
      background-color: #fff;
      text-align: center;
      border-radius: 50%;
      margin-top: 20px;
      display: block;
      position: relative;
      box-shadow: 0 0 20px 0 rgba(0,0,0,0.1);
      .iconfont {
        font-size: 16px;
        color: #4c4c4c;
        position: absolute;
        top: 50%;
        left: 50%;
        transform: translate(-50%, -50%);
        &.ri-message-ai-3-line {
          color: var(--primary-color);
          opacity: .6;
        }
      }
    }
  }
}
</style>
